﻿import type { RequestOptions } from '@@/plugin-request/request';
import { request } from '@@/plugin-request/request';
import type { RequestConfig } from '@umijs/max';
import { message } from 'antd';
import { authService } from '@/authService';

const publicPaths = ['/auth/generate', '/auth/verify', '/auth/login'];

/**
 * @name 错误处理
 * pro 自带的错误处理， 可以在这里做自己的改动
 * @doc https://umijs.org/docs/max/request#配置
 */
export const errorConfig: RequestConfig = {
  // 设置超时时间（5秒）
  timeout: 5000,

  // 错误处理配置
  errorConfig: {
    // 错误抛出 http错误不会进入 200会
    errorThrower: (res) => {
      const { code, message } = res as unknown as API.ResponseStructure;
      if (typeof res === 'object' && 'code' in res && code !== 0) {
        const error: any = new Error(message);
        error.name = 'BizError';
        error.info = res;
        throw error;
      }
    },

    // 错误接收及处理
    errorHandler: async (error: any, opts: { skipErrorHandler?: boolean }) => {
      // 接口请求时如果配置了跳过错误处理，则直接抛出错误
      if (opts?.skipErrorHandler) throw error;

      // 开发环境打印错误详情
      if (process.env.NODE_ENV === 'development') {
        console.error('Request error details:', error);
      }

      if (error.status === 401) {
        if (error.info?.code === 40101) {
          // 清除本地存储的 token 等信息  跳转登录接口
          authService.clearTokens();
          // 跳转到登录页，可以记录当前地址以便登录后返回
          window.location.href = `/user/login?redirect=${encodeURIComponent(
            window.location.href,
          )}`;
          return;
        }

        // 获取原始请求配置（umi request的错误对象中包含config）
        const originalRequestConfig = error.config as RequestOptions;
        // 定义重试函数：用新token重新发起请求
        const retryRequest = async (newToken: string) => {
          // 复制原始配置，更新Authorization头
          const newConfig = { ...originalRequestConfig };
          if (newConfig.headers) {
            newConfig.headers.Authorization = `Bearer ${newToken}`;
          }
          // 重试时跳过错误处理，避免重复进入此逻辑
          newConfig.skipErrorHandler = true;

          if (!newConfig.url) {
            throw new Error('URL is required');
          }
          return request(newConfig.url, newConfig);
        };

        // 利用authService的刷新队列，等待token刷新后执行重试
        return authService
          .refreshToken()
          .then(retryRequest)
          .catch((refreshError) => {
            authService.clearTokens();
            message.error('登录已过期，请重新登录');
            window.location.href = `/user/login?redirect=${encodeURIComponent(
              window.location.href,
            )}`;
            return Promise.reject(refreshError);
          });
      }

      if (error.name === 'BizError') {
        message.error(error.info?.message || error.message || '业务错误');
        return;
      }

      // 其他错误处理
      if (error.response?.data?.message) {
        message.error(error.response.data.message);
      } else if (error.request) {
        message.error('网络请求失败，请检查网络连接');
      } else {
        message.error('请求发生错误');
      }
    },
  },

  // 请求拦截器（使用登录后的token）
  requestInterceptors: [
    async (config: RequestOptions) => {
      const isPublic = publicPaths.some((path) => config.url?.startsWith(path));
      if (isPublic) {
        return config;
      }
      // 检查并刷新Token
      const token = await authService.checkAndRefreshToken();
      if (token && config.headers) {
        config.headers.Authorization = `Bearer ${token}`;
      }
      return config;
    },
  ],

  // 响应拦截器
  responseInterceptors: [
    // 成功响应拦截（2xx状态码，类型为AxiosResponse）
    (response) => {
      const { data } = response; // 直接从response获取data，无需response.response
      if (data && typeof data === 'object' && 'code' in data) {
        const res = data as unknown as API.ResponseStructure;
        return { ...response, data: res.code === 0 ? res.data : res };
      }
      return response;
    },
  ],
};
